1 module std.exception;
2 import std.traits;
3 
4 void enforce(bool cond, lazy string onThrow, string file = __FILE__, size_t line = __LINE__) pure @trusted
5 {
6     if(cond)
7         throw new Exception(onThrow, null, file, line);
8 }
9 
10 void enforce(bool cond, lazy Exception onThrow, string file = __FILE__, size_t line = __LINE__) pure @trusted
11 {
12     if(cond)
13         throw onThrow;
14 }
15 void enforce(T)(bool cond, lazy string onThrow, string file = __FILE__, size_t line = __LINE__) pure @trusted
16 {
17     if(cond)
18         throw new T(onThrow, file, line);
19 }
20 
21 
22 
23 
24 
25 CommonType!(T[], U[]) overlap(T, U)(T[] a, U[] b) @trusted
26 if (is(typeof(a.ptr < b.ptr) == bool))
27 {
28     import std.algorithm.comparison : min;
29 
30     auto end = min(a.ptr + a.length, b.ptr + b.length);
31     // CTFE requires pairing pointer comparisons, which forces a
32     // slightly inefficient implementation.
33     if (a.ptr <= b.ptr && b.ptr < a.ptr + a.length)
34     {
35         return b.ptr[0 .. end - b.ptr];
36     }
37 
38     if (b.ptr <= a.ptr && a.ptr < b.ptr + b.length)
39     {
40         return a.ptr[0 .. end - a.ptr];
41     }
42 
43     return null;
44 }
45 
46 package enum isUnionAliased(T, size_t i) = isUnionAliasedImpl!T(T.tupleof[i].offsetof);
47 private bool isUnionAliasedImpl(T)(size_t offset)
48 {
49     int count = 0;
50     foreach (i, U; typeof(T.tupleof))
51         if (T.tupleof[i].offsetof == offset)
52             ++count;
53     return count >= 2;
54 }
55 
56 
57 /**
58 Checks whether a given source object contains pointers or references to a given
59 target object.
60 
61 Params:
62     source = The source object
63     target = The target object
64 
65 Bugs:
66     The function is explicitly annotated `@nogc` because inference could fail,
67     see $(LINK2 https://issues.dlang.org/show_bug.cgi?id=17084, Bugzilla issue 17084).
68 
69 Returns: `true` if `source`'s representation embeds a pointer
70 that points to `target`'s representation or somewhere inside
71 it.
72 
73 If `source` is or contains a dynamic array, then, then these functions will check
74 if there is overlap between the dynamic array and `target`'s representation.
75 
76 If `source` is a class, then it will be handled as a pointer.
77 
78 If `target` is a pointer, a dynamic array or a class, then these functions will only
79 check if `source` points to `target`, $(I not) what `target` references.
80 
81 If `source` is or contains a union or `void[n]`, then there may be either false positives or
82 false negatives:
83 
84 `doesPointTo` will return `true` if it is absolutely certain
85 `source` points to `target`. It may produce false negatives, but never
86 false positives. This function should be prefered when trying to validate
87 input data.
88 
89 `mayPointTo` will return `false` if it is absolutely certain
90 `source` does not point to `target`. It may produce false positives, but never
91 false negatives. This function should be prefered for defensively choosing a
92 code path.
93 
94 Note: Evaluating $(D doesPointTo(x, x)) checks whether `x` has
95 internal pointers. This should only be done as an assertive test,
96 as the language is free to assume objects don't have internal pointers
97 (TDPL 7.1.3.5).
98 */
99 bool doesPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @nogc @trusted pure nothrow
100 if (__traits(isRef, source) || isDynamicArray!S ||
101     is(S == U*, U) || is(S == class))
102 {
103     static if (is(S == U*, U) || is(S == class) || is(S == interface))
104     {
105         const m = *cast(void**) &source;
106         const b = cast(void*) &target;
107         const e = b + target.sizeof;
108         return b <= m && m < e;
109     }
110     else static if (is(S == struct) || is(S == union))
111     {
112         foreach (i, Subobj; typeof(source.tupleof))
113             static if (!isUnionAliased!(S, i))
114                 if (doesPointTo(source.tupleof[i], target)) return true;
115         return false;
116     }
117     else static if (isStaticArray!S)
118     {
119         static if (!is(S == void[n], size_t n))
120         {
121             foreach (ref s; source)
122                 if (doesPointTo(s, target)) return true;
123         }
124         return false;
125     }
126     else static if (isDynamicArray!S)
127     {
128         import std.array : overlap;
129         return overlap(cast(void[]) source, cast(void[])(&target)[0 .. 1]).length != 0;
130     }
131     else
132     {
133         return false;
134     }
135 }
136 
137 // for shared objects
138 /// ditto
139 bool doesPointTo(S, T)(auto ref const shared S source, ref const shared T target) @trusted pure nothrow
140 {
141     return doesPointTo!(shared S, shared T, void)(source, target);
142 }
143 
144 mixin template basicExceptionCtors()
145 {
146     /++
147         Params:
148             msg  = The message for the exception.
149             file = The file where the exception occurred.
150             line = The line number where the exception occurred.
151             next = The previous exception in the chain of exceptions, if any.
152     +/
153     this(string msg, string file = __FILE__, size_t line = __LINE__,
154          Throwable next = null) @nogc @safe pure nothrow
155     {
156         super(msg, file, line, next);
157     }
158 
159     /++
160         Params:
161             msg  = The message for the exception.
162             next = The previous exception in the chain of exceptions.
163             file = The file where the exception occurred.
164             line = The line number where the exception occurred.
165     +/
166     this(string msg, Throwable next, string file = __FILE__,
167          size_t line = __LINE__) @nogc @safe pure nothrow
168     {
169         super(msg, file, line, next);
170     }
171 }
172 
173 immutable(T)[] assumeUnique(T)(T[] array) pure nothrow
174 {
175     return .assumeUnique(array);    // call ref version
176 }
177 /// ditto
178 immutable(T)[] assumeUnique(T)(ref T[] array) pure nothrow
179 {
180     auto result = cast(immutable(T)[]) array;
181     array = null;
182     return result;
183 }
184 /// ditto
185 immutable(T[U]) assumeUnique(T, U)(ref T[U] array) pure nothrow
186 {
187     auto result = cast(immutable(T[U])) array;
188     array = null;
189     return result;
190 }